/*
 *  ssax.h
 *  
 *
 *  Created by dragon on 9/5/05.
 *  Copyright 2005 __GoatBits__. All rights reserved.
 *
 */
 
 #include <iostream>
 #include <fstream>

#ifndef SSAX_H
#define SSAX_H

class SSAttribute
{
  public:
    SSAttribute();
    SSAttribute(const char*,const char*);
   ~SSAttribute();
    void               set(const char*,const char*);
    void               add(const char*,const char*);
    const char*        getTag();
    const char*        getValue();
    void               setNext(SSAttribute*);
    SSAttribute*       getNext();
    SSAttribute*       find(const char*);
  private:
    char        *name;
    char        *value;
    SSAttribute *next;
};

enum SSJUMP
{
    SSJ_START, // '<'
    SSJ_END,   // '</'
    SSJ_SPACE, // ' ' '\n,t,r'
    SSJ_CLOSE, // '>'
    SSJ_OTHER, // any other charter.
    SSJ_ERROR  // unexpected charter.
};

class SSSAX
{
  public:
      SSSAX();
      SSSAX(const char*);
      virtual ~SSSAX();

      void setFile(const char*,bool oc=true);
      bool fileOutOpen(){return xml_out.is_open();} 
      void closeOutFile(){xml_out.close();} 
      bool fileInOpen(){return xml_in.is_open();} // no user access
      void closeInFile(){xml_in.close();} // no user access
      // make a copy of the data I am going to delete it.
      virtual void startTagCB(void *,const char*,SSAttribute*)=0;
      virtual void charDataCB(void *,const char*)=0;
      virtual void endTagCB(void *,const char*)=0;

      void   setUserData(void *ud){user_data = ud;}
      short  getLineCount(){return line_count;}
      void   doParse();
      // new code
      void   readyWrite();
      void   parse(); // no user access
      bool   getLine(unsigned keep=0);
      void   writeStartTag(unsigned,const char*); // space indent, tag string + attributes.
      void   writeAttTag(const char*);            // attribute tag.
      void   writeAttValue(const char*);          // attribute tag value.
      void   writeStartTagClose();                // close start tag.
      void   writeData(const char*);              // string of data.
      void   writeEndTag(unsigned,const char*);   // space indent, tag string.  '/' not needed.
      char*  charPack(const char*,const char*);   // utility to pack data into a char.
      bool   newFile(){return new_file;}          // file does not exist must be new.
  private:
      char          *file_name;   // name of xml file
      void          *user_data;   // pointer to user data for callbacks.
      std::ifstream xml_in;       // in file stream
      std::ofstream xml_out;      // out file stream
      SSAttribute   *attributes;  // list of attributes 
      SSAttribute   *attr_current; // index to current attribute
      unsigned       attr_size;   // number of spaces in attribute array
      unsigned       attr_count;  // number of attribute in array
      char          *data_char;   // current assembled word
      unsigned       data_size;   // max size of data_char
      unsigned       data_count;  // number of chars in data_char.
      char          *tag_name;    // name of current tag.
      unsigned       tag_length;  // max length of tag_name
      short          line_count;  // current lenght of tag_name
      char          *parse_line;  // data read in from file
      unsigned       parse_size;  // max size of parse_line
      unsigned       parse_count; // current length of parse_line
      bool           new_file;    // file does not exist it must be new.

      void     init();
      void     addAttribute(const char*,const char*);
      void     addChar(char**,unsigned&,char);
      void     clearAttr();
      bool     eof;
      unsigned parseTag(char**, unsigned&);
      unsigned parseAttName(char**, unsigned&);
      unsigned parseAttValue(char**, unsigned&);
      unsigned parseData(char**, unsigned&);
      unsigned parseString(char**, unsigned&);
      SSJUMP   jumpSpace();
};

#endif

